package forum.client;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.*;

import forum.shared.*;

public class SearchScreen extends Screen {
	private RadioButton authorBtn;
	private RadioButton contentBtn;
	private FlowPanel radioPanel;
	private TextBox searchTxt;
	private Button searchBtn;
	private Button backBtn;
	private FlexTable headerTbl;
	private Label headerLbl;
	
	private FlexTable buttonsTbl;
	private FlexTable resultsTbl;
	
	private final int HITS_PER_PAGE = 5;
	private int from;
	private String searchStr;

	/**
	 * Default constructor.
	 */
	public SearchScreen() {
		createComponents();
		setStyle();
		setTabOrder();
		setActions();
		setupScreenDisplay();
	}

	protected void createComponents() {
		this.authorBtn = new RadioButton("searchBy", "author");
		this.contentBtn = new RadioButton("searchBy", "content");
		this.radioPanel = new FlowPanel();
		this.searchTxt = new TextBox();
		this.searchBtn = new Button("Search");
		this.backBtn = new Button("Back");
		this.buttonsTbl = new FlexTable();
		this.resultsTbl = new FlexTable();
		this.headerTbl = new FlexTable();
		this.headerLbl = new Label("Bannana Forum Search");
	}

	protected void setStyle() {
		this.searchBtn.addStyleName("button");
		this.backBtn.addStyleName("button");
		this.searchTxt.addStyleName("fieldcell");
		this.buttonsTbl.addStyleName("buttonsTable");
		this.resultsTbl.addStyleName("blueStyleTable");
		this.headerTbl.addStyleName("horizontalPanel");
		this.headerLbl.addStyleName("title");
	}
	
	protected void setTabOrder() {
		this.searchTxt.setTabIndex(0);
		this.authorBtn.setTabIndex(1);
		this.contentBtn.setTabIndex(2);
		this.searchBtn.setTabIndex(3);
		this.backBtn.setTabIndex(4);
	}

	protected void setActions() {
		this.backBtn.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				new MainScreen().setupDisplayInMainPanel();
			}
		});
		
		this.backBtn.addKeyPressHandler(new KeyPressHandler() {
			@Override
			public void onKeyPress(KeyPressEvent event) {
				if (event.getCharCode() == KeyCodes.KEY_ENTER)
					new MainScreen().setupDisplayInMainPanel();
			}
		});
		
		this.searchBtn.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				from = 0;
				search();
			}
		});
		
		this.searchBtn.addKeyPressHandler(new KeyPressHandler() {
			@Override
			public void onKeyPress(KeyPressEvent event) {
				if (event.getCharCode() == KeyCodes.KEY_ENTER)
					from = 0;
					search();
			}
		});
	}
	
	protected void setupScreenDisplay() {
		this.authorBtn.setValue(true);
		this.radioPanel.add(this.authorBtn);
		this.radioPanel.add(this.contentBtn);
		this.buttonsTbl.setWidget(0, 0, new Label("Enter search string: "));
		this.buttonsTbl.setWidget(0, 1, this.searchTxt);
		this.buttonsTbl.setWidget(0, 2, this.radioPanel);
		this.buttonsTbl.setWidget(0, 3, this.searchBtn);
		this.buttonsTbl.setWidget(0, 4, backBtn);
	}
	
	public void setupDisplayInMainPanel() {
		Panel mainPanel = MainPanel.get();
		mainPanel.clear();
		mainPanel.add(this.headerLbl);
		mainPanel.add(this.buttonsTbl);
		mainPanel.add(this.headerTbl);
		mainPanel.add(this.resultsTbl);
//		mainPanel.add(this.backBtn);
	}
	
	public void search() {
		this.searchBtn.setEnabled(false);
		this.resultsTbl.clear(true);
		ForumServiceAsync forumSvc = GWT.create(ForumService.class);
		
		// Set up the callback object.
	    AsyncCallback<ServerResponse> callback = new AsyncCallback<ServerResponse>() {
	    	public void onFailure(Throwable caught) {
	    		Window.alert("Communication error. Please retry later.");
	    		searchBtn.setEnabled(true);
	    	}
	    	//On successful communication.
			@Override
			public void onSuccess(ServerResponse response) {
				if (response!=null && response.hasExecuted()) {
					displayResults(response);
	            } 
				else {
					headerTbl.clear();
					headerTbl.setWidget(0, 0, (new Label(response!=null ? 
							response.getResponse() : "Unknown Error...")));
	            }
				searchBtn.setEnabled(true);
			}
	    };
	    
		// Make the call to the forum service.
	    String input = getInput();
	    if (input != null)
	    	forumSvc.sendMsg(input, callback);
	    else
	    	searchBtn.setEnabled(true);
	}

	@Override
	protected String getInput() {
		String d = Delimiters.MSG_PARTS;
		String criteria;
		
		if (this.searchTxt.getText().isEmpty()) {
			Window.alert("Please enter a search string.");
			return null;
		}
		criteria = this.authorBtn.getValue() ? "AUTHOR" : "CONTENT";
		this.searchStr = this.searchTxt.getText();
		int to = this.from + this.HITS_PER_PAGE - 1;
		
		return "Search" + d + criteria + d + this.searchStr + 
		d + this.from + d + to; 
	}

	/**
	 * @param response
	 */
	private void displayResults(ServerResponse response) {
		String[] hits = response.getResponse().split(Delimiters.MSG_PARTS);
		final int total = Integer.parseInt(hits[0]);
		
		// poplute header panel
		headerTbl.clear();
		int to = from + total;
		headerTbl.setWidget(0, 0, new Label("Displaying results " + this.from + 
				"-" + to + " for: " + this.searchStr + "   "));
		Label prevLbl = new Label("prev");
		Label nextLbl = new Label("next");
		
		if (total != 0) {
			nextLbl.addStyleName("link");
			nextLbl.addClickHandler(new ClickHandler() {
				@Override
				public void onClick(ClickEvent event) {
					from += HITS_PER_PAGE;
					search();
				}
			});
		}
		
		if (from > 1) {
			prevLbl.addStyleName("link");
			prevLbl.addClickHandler(new ClickHandler() {
				@Override
				public void onClick(ClickEvent event) {
					from -= HITS_PER_PAGE;
					search();
				}
			});
		}
		
		headerTbl.setWidget(0, 1, prevLbl);
		headerTbl.setWidget(0, 2, nextLbl);
		
		
		// populate resultsTable
		for (int i=1; i<=total; i++) {
			String hit[] = hits[i].split(Delimiters.SEARCH_HIT_PARTS);
			final int postId = Integer.parseInt(hit[hit.length-1]);
			
			// author, title, date, scor
			for (int j=0; j<hit.length-1; j++)
				this.resultsTbl.setText(i, j, hit[j]);
			
			// "jump to forum" button
			this.resultsTbl.setWidget(i, hit.length-1, 
					new Button("View", new ClickHandler() {

						@Override
						public void onClick(ClickEvent event) {
							new MainScreen().openSeacrhHit(postId, SearchScreen.this);
						}
					}));
		}
		
		this.searchBtn.setEnabled(true);
	}
}

